//
//  HACRouter.m
//  HACRouter
//
//  Created by Chengjie on 2019/4/25.
//  Copyright © 2019 Happy. All rights reserved.
//

#import "HACRouter.h"
#import "HACRouterPath.h"
#import "NSObject+HACInvocation.h"

#if DEBUG_ROUTER
static NSMutableDictionary<NSString *, NSMutableArray<NSString *> *> *hacLogMap = nil;
#endif
static NSMutableDictionary<NSString *, NSString *> *hacControllerMap = nil;
static NSMutableDictionary<NSString *, NSMutableArray<NSString *> *> *hacSelMap = nil;
static NSSet<NSString *> *hacWhiteSchemeSet = nil;
static NSSet<NSString *> *hacWhiteHostSet = nil;

@implementation HACRouter

+ (void)configRouterWhiteHosts:(NSSet *)hosts whiteSchemes:(NSSet *)schemes {
    if (!hacWhiteSchemeSet) {
        hacWhiteSchemeSet = schemes;
    }
    if (!hacWhiteHostSet) {
        hacWhiteHostSet = hosts;
    }
#if DEBUG_ROUTER
    NSLog(@"RouterWhiteScheme: %@", hacWhiteSchemeSet);
    NSLog(@"RouterWhiteHost: %@", hacWhiteHostSet);
#endif
}

+ (void)generateRouterLogWithMacFilePath:(NSString *)filePath {
#if DEBUG_ROUTER
    // 非DEBUG_ROUTER模式下不输出日志和头文件，优化启动时间
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSMutableDictionary *logDic = [NSMutableDictionary dictionary];
        [hacLogMap enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSMutableArray<NSString *> * _Nonnull obj, BOOL * _Nonnull stop) {
            NSMutableDictionary *routerDic = [NSMutableDictionary dictionary];
            routerDic[@"ClsRef"] = [hacControllerMap valueForKey:key];
            routerDic[@"FuncRef"] = obj;
            [logDic setValue:routerDic forKey:key];
        }];
        NSError *error = nil;
        NSData *logMapData = [NSJSONSerialization dataWithJSONObject:logDic options:NSJSONWritingPrettyPrinted error:&error];
        NSString *logMapStr = [[NSString alloc] initWithData:logMapData encoding:NSUTF8StringEncoding];
        if (!error && filePath) {
            [logMapStr writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
        }
        NSLog(@"%@", logDic);
    });
#endif
}

+ (void)generateRouterHeaderWithMacFilePath:(NSString *)filePath {
#if DEBUG_ROUTER
    // 非DEBUG_ROUTER模式下不输出日志和头文件，优化启动时间
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSMutableString *headerStr = [NSMutableString string];
        [hacLogMap enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSMutableArray<NSString *> * _Nonnull obj, BOOL * _Nonnull stop) {
            NSString *clsRef = [hacControllerMap valueForKey:key];
            if (!headerStr.length) {
                [headerStr appendFormat:@"// %@ ===> %@\n", key, clsRef];
            } else {
                [headerStr appendFormat:@"\n\n// %@ ===> %@\n", key, clsRef];
            }
            [obj enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                [headerStr appendFormat:@"%@\n", obj];
            }];
        }];
        if (!headerStr || !headerStr.length) {
            return;
        }
        [headerStr writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
        NSLog(@"%@", headerStr);
    });
#endif
}

+ (id)routerWithUrls:(NSString *)urls {
    return [self routerWithUrls:urls customParser:nil];
}

+ (id)routerWithUrls:(NSString *)urls customParser:(id<HACRouterUrlParserRules>)parser {
    HACRouterPath *path = [HACRouterPath routerPathWithUrls:urls whiteHosts:hacWhiteHostSet whiteSchemes:hacWhiteSchemeSet customParser:parser];
    if (!path || !path.routerName || !path.routerName.length) {
        return nil;
    }
    NSString *clsName = [hacControllerMap valueForKey:path.routerName];
    if (!clsName || !clsName.length) {
        return nil;
    }
    NSArray<NSString *> *selList = [hacSelMap valueForKey:path.routerName];
    [path figureBestInitSelectorAndArgumentsInSelList:selList];
    if (!path.bestInitSelector || !path.bestInitSelector.length) {
        return nil;
    }
    
    Class cls = NSClassFromString(clsName);
    SEL sel = NSSelectorFromString(path.bestInitSelector);
    id controller = [[cls alloc] hac_performInitSelector:sel withArguments:path.bestInitArgs];
    return controller;
}

+ (Class)getClassForPath:(NSString *)path {
    return NSClassFromString([hacControllerMap valueForKey:path]);
}

@end

void regest_router_key_value(NSString *router_key, NSString *controller_name, NSString *router_imp, NSString *sel_name) {
#if DEBUG_ROUTER
    // 非DEBUG_ROUTER模式下不收集LOG日志
    if (!hacLogMap) {
        hacLogMap = [NSMutableDictionary dictionary];
    }
    NSMutableArray *imps = [hacLogMap valueForKey:router_key];
    if (!imps) {
        imps = [NSMutableArray array];
        [hacLogMap setValue:imps forKey:router_key];
    }
    [imps addObject:router_imp];
#endif
    
    if (!hacSelMap) {
        hacSelMap = [NSMutableDictionary dictionary];
    }
    if (!hacControllerMap) {
        hacControllerMap = [NSMutableDictionary dictionary];
    }
    NSMutableArray *sels = [hacSelMap valueForKey:router_key];
    if (!sels) {
        sels = [NSMutableArray array];
        [hacSelMap setValue:sels forKey:router_key];
        [hacControllerMap setValue:controller_name forKey:router_key];
    }
    [sels addObject:sel_name];
}


